package com.winhxd.b2c.order.service.impl;

import com.winhxd.b2c.common.cache.Cache;
import com.winhxd.b2c.common.cache.Lock;
import com.winhxd.b2c.common.cache.RedisLock;
import com.winhxd.b2c.common.constant.BusinessCode;
import com.winhxd.b2c.common.constant.CacheName;
import com.winhxd.b2c.common.constant.OrderSMSConstant;
import com.winhxd.b2c.common.domain.PagedList;
import com.winhxd.b2c.common.domain.customer.model.CustomerShoppingMallRule;
import com.winhxd.b2c.common.domain.message.condition.SMSCondition;
import com.winhxd.b2c.common.domain.order.condition.OrderAfterSaleApplyCondition;
import com.winhxd.b2c.common.domain.order.condition.OrderAfterSaleCondition;
import com.winhxd.b2c.common.domain.order.condition.OrderQueryCondition;
import com.winhxd.b2c.common.domain.order.enums.*;
import com.winhxd.b2c.common.domain.order.model.*;
import com.winhxd.b2c.common.domain.order.vo.OrderAfterSaleDetailForRebate;
import com.winhxd.b2c.common.domain.order.vo.OrderAfterSaleDetailVO;
import com.winhxd.b2c.common.domain.order.vo.OrderInfoAfterSaleVO;
import com.winhxd.b2c.common.domain.order.vo.OrderInfoVO;
import com.winhxd.b2c.common.exception.BusinessException;
import com.winhxd.b2c.common.mq.event.EventMessageSender;
import com.winhxd.b2c.common.util.JsonUtil;
import com.winhxd.b2c.common.util.MessageSendUtils;
import com.winhxd.b2c.order.dao.*;
import com.winhxd.b2c.order.service.OrderAfterSaleDetailService;
import com.winhxd.b2c.order.service.OrderService;
import com.winhxd.b2c.order.util.OrderUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;


@Service
public class OrderAfterSaleDetailServiceImpl implements OrderAfterSaleDetailService {

	private static final Logger LOGGER = LoggerFactory.getLogger(OrderAfterSaleDetailServiceImpl.class);

    private static final int AFTER_SALE_UPDATE_LOCK_EXPIRES_TIME = 2000;
    private static final int ORDER_UPDATE_LOCK_EXPIRES_TIME = 5000;
    public static final int TEMP_ORDER_STATUS_NORMAL = 1;
    public static final int TEMP_ORDER_STATUS_FINISHED = 2;
    public static final int TEMP_ORDER_STATUS_CLOSE = 3;
    private static final int MAX_ORDER_POSTFIX = 99999;

	@Autowired
	private OrderAfterSaleDetailMapper afterSaleDetailMapper;

	@Autowired
	private OrderAfterSaleMapper afterSaleMapper;

	@Autowired
	private OrderAfterSaleDetailMapper orderAfterSaleDetailMapper;

	@Autowired
	private OrderCancelInfoMapper orderCancelInfoMapper;

    @Autowired
    private OrderLogMapper orderLogMapper;

    @Autowired
    private OrderInfoMapper infoMapper;

	@Resource
	public OrderService orderService;
	@Resource
	public OrderRebateRecordMapper orderRebateRecordMapper;

    @Autowired
    private EventMessageSender eventMessageSender;

    @Autowired
    private Cache cache;

    @Autowired
    MessageSendUtils messageSendUtils;

    /**
     * @Description 保存售后明细
     * @author lining
     * @date 2019/1/8 14:12:23
     * @param afterSaleDetail
     * @return Integer
     */
	@Override
	public Integer saveOrderAfterSaleDetail(OrderAfterSaleDetail afterSaleDetail) {
		return afterSaleDetailMapper.insertSelective(afterSaleDetail);
	}

    /**
     * @Description 保存售后信息
     * @author lining
     * @date 2019/1/8 14:19:02
     * @param condition
     * @return
     */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveOrderAfterSale(OrderAfterSaleApplyCondition condition) {
		OrderAfterSaleDetail afterSaleDetail = new OrderAfterSaleDetail();
		this.setAfterSaleDetailProperty(condition,afterSaleDetail);
        //验证订单状态
        this.validateOrderStatus(afterSaleDetail);
        //验证售后
		this.validateApply(afterSaleDetail);
        String lockKey = CacheName.CACHE_KEY_APPLY_AFTER_SALE+afterSaleDetail.getOrderNo();
        if(null != afterSaleDetail.getSkuId()) {
            lockKey+=afterSaleDetail.getSkuId();
        }
        Lock lock = new RedisLock(cache, lockKey, AFTER_SALE_UPDATE_LOCK_EXPIRES_TIME);
        if (lock.tryLock()) {
            try {
                //售后单号
                String afterSaleNo = this.generateAfterSaleNo(afterSaleDetail);
                OrderAfterSale afterSale = new OrderAfterSale();
                afterSale.setOrderNo(afterSaleDetail.getOrderNo());
                afterSale.setOrderDetailId(condition.getOrderDetailId());

                //保存售后信息
                LOGGER.info("保存售后信息-----saveOrderAfterSale-----售后信息-----{}", JsonUtil.toJSONString(afterSale));
                afterSaleMapper.insertSelective(afterSale);

                afterSaleDetail.setAfterSaleNo(afterSaleNo);
                afterSaleDetail.setAfterSaleId(afterSale.getId());
                //保存售后明细信息
                LOGGER.info("保存售后信息-----saveOrderAfterSale-----售后明细信息-----{}", JsonUtil.toJSONString(afterSaleDetail));
                afterSaleDetailMapper.insertSelective(afterSaleDetail);

                OrderCancelInfo cancelInfo = new OrderCancelInfo();
                this.dealCancelInfo(afterSaleDetail,condition,cancelInfo);
                //售后原因表
                LOGGER.info("保存售后信息-----saveOrderAfterSale-----售后原因-----{}", JsonUtil.toJSONString(cancelInfo));
                orderCancelInfoMapper.insertSelective(cancelInfo);
                try{
                    //发送短信提示
                    this.sendMessage(afterSaleDetail);
                    //订单日志
                    this.saveOrderLog(afterSaleDetail,CommonStatusEnum.YES.getTypeCode());
                }catch (Exception e){
                    LOGGER.info("售后申请-短信/日志异常,不回滚",e);
                }
            } finally {
                lock.unlock();
            }
        }else {
            throw new BusinessException(BusinessCode.CODE_440602);
        }
	}

	/**
	 * @Description 获得售后发送短信内容
	 * @author lining
	 * @date 2019/1/19 11:46:59
	 * @param afterSaleDetail
	 * @return
	 */
	private String getAfterSaleMessageContent(OrderAfterSaleDetail afterSaleDetail){
        SimpleDateFormat formatter=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String contentData = formatter.format(afterSaleDetail.getCreated());
        String afterSaleContent=getAfterSaleContent(afterSaleDetail);
       return MessageFormat.format(OrderSMSConstant.afterSaleApply_template,contentData,afterSaleContent, afterSaleDetail.getOrderNo());
    }

    /**
     * @Description 获取售后发送短信号码
     * @author lining
     * @date 2019/1/19 11:47:21
     * @param
     * @return
     */
    private String getAfterSaleMobile(){
        CustomerShoppingMallRule customerShoppingMallRule = JsonUtil.parseJSONObject(cache.get(CacheName.SHOPPING_MALL_RULE), CustomerShoppingMallRule.class);
        if(null == customerShoppingMallRule){
            LOGGER.info("未获得商城营业信息【售后申请短信通知】!!");
            throw new BusinessException(BusinessCode.CODE_440611);
        }
        return customerShoppingMallRule.getAftersaleMobile();
    }

    /**
     * @Description 组装售后短信内容
     * @author lining
     * @date 2019/1/19 11:47:40
     * @param afterSaleDetail
     * @return
     */
    private String getAfterSaleContent(OrderAfterSaleDetail afterSaleDetail){
        String afterSaleContent = "";
        //1-待发货-仅退款
        if(afterSaleDetail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.WAIT_DELIVERING_REFUND.getTypeCode().intValue()) {
            afterSaleContent = " 新退款申请（订单尚未发货）";
        //2-已发货退货退款 || 5-已收货退货退款
        }else if(afterSaleDetail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.WAIT_RECEIVING_REFUND_AND_RETURN.getTypeCode().intValue()
            || afterSaleDetail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.FINISHED_REFUND_AND_RETURN.getTypeCode().intValue()) {
            afterSaleContent="新退货申请（订单已发货）";
        //3-已发货换货 || 6-已收货换货
        }else if(afterSaleDetail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.WAIT_RECEIVING_EXCHANGE.getTypeCode().intValue()
                || afterSaleDetail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.FINISHED_EXCHANGE.getTypeCode().intValue()) {
            afterSaleContent="新换货申请（订单已发货）";
        }
        return afterSaleContent;
    }

    /**
     * @Description 发送售后短信
     * @author lining
     * @date 2019/1/19 11:48:00
     * @param afterSaleDetail
     * @return
     */
    public void sendMessage(OrderAfterSaleDetail afterSaleDetail){
        String mobileParam = this.getAfterSaleMobile();
        if(StringUtils.isBlank(mobileParam)){
            LOGGER.info("售后申请发送短信手机号为空！！");
            return;
        }
        String content = this.getAfterSaleMessageContent(afterSaleDetail);
        String[] mobile = mobileParam.split(",");
        for(String sendMobile : mobile){
            SMSCondition sMSCondition = new SMSCondition();
            sMSCondition.setContent(content);
            sMSCondition.setMobile(sendMobile);
            messageSendUtils.sendSms(sMSCondition);
            LOGGER.info("售后【{}】申请发送短信-----手机号：{},短信内容：{}",OrderAfterSaleTypeEnum.getDescByCode(afterSaleDetail.getAfterSaleType().intValue()),sendMobile,content);
        }
    }

	/**
	 * @Description 售后订单日志
	 * @author lining
	 * @date 2019/1/12 16:12:27
	 * @param afterSaleDetail  flag
	 * @return
	 */
	private void saveOrderLog(OrderAfterSaleDetail afterSaleDetail,int flag){
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderNo(afterSaleDetail.getOrderNo());
        orderLog.setSkuId(afterSaleDetail.getSkuId());
        String pre="";
        orderLog.setCreated(new Date());
        if(flag==CommonStatusEnum.NO.getTypeCode()){
            pre+=OrderOperationPropertyEnum.AFTER_SALE_CANCEL.getPropertyDes();
        }else if(flag==CommonStatusEnum.YES.getTypeCode()){
            pre+=OrderOperationPropertyEnum.AFTER_SALE_APPLY.getPropertyDes();
        }
        String operationPropertity =pre.concat("【").concat(OrderAfterSaleTypeEnum.getDescByCode(afterSaleDetail.getAfterSaleType())).concat("】");
        orderLog.setOperationProperty(operationPropertity);
        LOGGER.info("售后申请订单日志-----saveOrderLog-----{}", JsonUtil.toJSONString(orderLog));
        orderLogMapper.insertSelective(orderLog);
    }

    /**
     * @Description 订单完成/关闭日志
     * @author lining
     * @date 2019/1/12 16:12:27
     * @param  flag
     * @return
     */
    private void saveOrderLog(String orderNo,int flag){
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderNo(orderNo);
        String content="";
        orderLog.setCreated(new Date());
        if(flag==CommonStatusEnum.NO.getTypeCode()){
            content=OrderOperationPropertyEnum.CLOSE_ORDER.getPropertyDes();
        }else if(flag==CommonStatusEnum.YES.getTypeCode()){
            content=OrderOperationPropertyEnum.FINISH_ORDER.getPropertyDes();
        }
        orderLog.setOperationProperty(content);
        LOGGER.info("订单完成/关闭日志-----saveOrderLog-----{}", JsonUtil.toJSONString(orderLog));
        orderLogMapper.insertSelective(orderLog);
    }

	/**
	 * @Description 售后原因赋值
	 * @author lining
	 * @date 2019/1/11 19:13:19
	 * @param afterSaleDetail  condition cancelInfo
	 * @return
	 */
	private void dealCancelInfo(OrderAfterSaleDetail afterSaleDetail,OrderAfterSaleApplyCondition condition,OrderCancelInfo cancelInfo){
        cancelInfo.setAfterSaleDetailId(afterSaleDetail.getId());
        cancelInfo.setOrderNo(afterSaleDetail.getOrderNo());
        cancelInfo.setOrderDictType(condition.getOrderDictType());
        cancelInfo.setOrderDictCode(condition.getOrderDictCode());

    }

    /**
     * @Description 验证订单是否发起过 待发货-退款 售后 且 未完成
     * @author lining
     * @date 2019/1/14 14:38:21
     * @param afterSaleDetail
     * @return true-是，false-否
     */
    private boolean validateAfterSaleComplate(OrderAfterSaleDetail afterSaleDetail){
        OrderAfterSaleDetail orderAfterSaleDetail = new OrderAfterSaleDetail();
        orderAfterSaleDetail.setAfterSaleType(OrderAfterSaleTypeEnum.WAIT_DELIVERING_REFUND.getTypeCode());
        orderAfterSaleDetail.setOrderNo(afterSaleDetail.getOrderNo());
        orderAfterSaleDetail.setCompleteStatus(CommonStatusEnum.NO.getTypeCode());
        return orderAfterSaleDetailMapper.getApplyCount(orderAfterSaleDetail)>0;
    }

    /**
     * @Description 修改售后信息
     * @author lining
     * @date 2019/1/8 15:28:13
     * @param afterSaleDetail
     * @return
     */
	@Override
	public Integer updateOrderAfterSaleDetail(OrderAfterSaleDetail afterSaleDetail) {
		return afterSaleDetailMapper.updateByPrimaryKeySelective(afterSaleDetail);
	}

	/**
	 * @Description 验证是否已经售后
	 * @author lining
	 * @date 2019/1/10 18:49:20
	 * @param afterSaleDetail
	 * @return true-已有售后 false-无售后
	 */
	@Override
	public boolean validateCanApply(OrderAfterSaleDetail afterSaleDetail){
		OrderAfterSaleDetail orderAfterSaleDetail = new OrderAfterSaleDetail();
		orderAfterSaleDetail.setOrderNo(afterSaleDetail.getOrderNo());
		orderAfterSaleDetail.setSkuId(afterSaleDetail.getSkuId());
		return orderAfterSaleDetailMapper.getApplyCount(orderAfterSaleDetail)>0;
	}


	/**
	 * @Description 验证订单是否发起过 待发货-退款 售后 且 审核通过
	 * @author lining
	 * @date 2019/1/14 14:38:21
	 * @param afterSaleDetail
	 * @return true-是，false-否
	 */
	private boolean validateAfterSaleRefund(OrderAfterSaleDetail afterSaleDetail){
        OrderAfterSaleDetail orderAfterSaleDetail = new OrderAfterSaleDetail();
        orderAfterSaleDetail.setAfterSaleType(OrderAfterSaleTypeEnum.WAIT_DELIVERING_REFUND.getTypeCode());
        orderAfterSaleDetail.setOrderNo(afterSaleDetail.getOrderNo());
        orderAfterSaleDetail.setResultStatus(AfterSaleAuditStatusEnum.YES.getTypeCode());
        return orderAfterSaleDetailMapper.getApplyCount(orderAfterSaleDetail)>0;
    }

	/**
	 * @Description 验证订单自动收货时间
	 * @author lining
	 * @date 2019/1/10 19:12:12
	 * @param orderNo
	 * @return false-未到收货时间 true-已经到收货时间
	 */
    @Override
	public boolean validateOrderAutoReceiveTime(String orderNo){
		OrderInfo oInfo = orderService.selectByOrderNo(orderNo);
		if(null != oInfo.getSendTime() && OrderUtils.isAutoRecive(oInfo.getSendTime(),oInfo.getAutoReceiveDay().intValue()*24*60)){
			return true;
		}
		return false;
	}

    /**
     * @Description 撤回售后申请
     * @author lining
     * @date 2019/1/10 20:28:13
     * @param afterSaleDetail
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer cancelOrderAfterSaleApply(OrderAfterSaleDetail afterSaleDetail) {
        OrderAfterSaleDetail detail = afterSaleDetailMapper.selectByPrimaryKey(afterSaleDetail.getId());
        //验证售后是否强制关闭
        this.validateCloseAfterSaleStatus(detail.getId());
        if(!this.validateCancel(detail)){
            LOGGER.info("售后申请已经审批，不能撤回！！");
            throw new BusinessException(BusinessCode.CODE_440605);
        }
        String lockKey = CacheName.CACHE_KEY_MODIFY_AFTER_SALE+detail.getOrderNo();
        if(null != detail.getSkuId()) {
            lockKey+=detail.getSkuId();
        }
        Lock lock = new RedisLock(cache, lockKey, AFTER_SALE_UPDATE_LOCK_EXPIRES_TIME);
        int result = 0;
        if (lock.tryLock()) {
            try {
                //修改售后
                LOGGER.info("撤回售后申请-----cancelOrderAfterSaleApply-----售后信息-----{}", JsonUtil.toJSONString(afterSaleDetail));
                result = afterSaleDetailMapper.updateByPrimaryKeySelective(afterSaleDetail);
                //修改订单状态
                this.updateOrderStatus(detail.getOrderNo());
                try{
                    //订单日志
                    this.saveOrderLog(detail,CommonStatusEnum.NO.getTypeCode());
                }catch (Exception e){
                    LOGGER.info("售后撤销申请-日志异常,不回滚",e);
                }
            } finally {
                lock.unlock();
            }
        }else {
            throw new BusinessException(BusinessCode.CODE_440603);
        }
        return result;
    }

    /**
     * @Description 验证是否能撤销
     * @author lining
     * @date 2019/1/14 12:50:05
     * @param detail
     * @return  true-可以，false-不可以
     */
    private boolean validateCancel(OrderAfterSaleDetail detail){
        //如果已经同意或者拒绝
        if(detail.getResultStatus().intValue() < AfterSaleAuditStatusEnum.PROCESSING.getTypeCode().intValue()){
            return false;
        }
        return true;
    }

    /**
     * @Description 修改订单状态
     * @author lining
     * @date 2019/1/12 16:03:23
     * @param orderNo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderStatus(String orderNo){
        int status = this.getOrderStatus(orderNo);
        if (status == TEMP_ORDER_STATUS_NORMAL) {
            LOGGER.info("订单未完成！！");
            return;
        }
        String lockKey = CacheName.CACHE_KEY_MODIFY_ORDER + orderNo;
        Lock lock = new RedisLock(cache, lockKey, ORDER_UPDATE_LOCK_EXPIRES_TIME);
        if (lock.tryLock()) {
            try {
                //修改订单信息
                this.modifyOrderStatus(orderNo,status);
                //修改收益状态
                this.updateRebateRecord(orderNo);

                if (status == TEMP_ORDER_STATUS_CLOSE) {
                    //订单日志
                    this.saveOrderLog(orderNo,CommonStatusEnum.NO.getTypeCode().intValue());
                }

                if (status == TEMP_ORDER_STATUS_FINISHED) {
                    //发送消息
                    this.sendMessage(orderNo);
                    //订单日志
                    this.saveOrderLog(orderNo,CommonStatusEnum.YES.getTypeCode().intValue());
                }
            } finally {
                lock.unlock();
            }
        } else {
            throw new BusinessException(BusinessCode.ORDER_IS_BEING_MODIFIED);
        }
    }

    /**
     * @Description 发送消息
     * @author lining
     * @date 2019/1/17 10:42:59
     * @param orderNo
     * @return
     */
    private void sendMessage(String orderNo){
        orderService.orderFinishSendEvent(orderNo);
    }

    /**
     * @Description 修改收益状态(订单闭环)
     * @author lining
     * @date 2019/1/17 10:39:40
     * @param orderNo
     * @return
     */
    @Override
    public void updateRebateRecord(String orderNo){
        //待发货退款完成
        if(this.getOrderStatusByAfterSale(orderNo)){
            OrderRebateRecord record = new OrderRebateRecord();
            record.setOrderNo(orderNo);
            record.setStatus(OrderRebateStatusEnum.HAS_CLOSED.getStatusCode());
            LOGGER.info("修改收益状态(已售后-审核同意 1-待发货-仅退款)-----updateRebateRecord-----收益信息-----{}", JsonUtil.toJSONString(record));
            orderRebateRecordMapper.updateByPrimaryKeySelective(record);
            return;
        }
        List<OrderAfterSaleDetailForRebate> lst = afterSaleDetailMapper.selectAfterSaleForRebateByOrderNo(orderNo);
        for (OrderAfterSaleDetailForRebate detail:lst) {
            //未售后
            if(detail.getAfterSaleType() == null){
                //未售后商品
                if( null == detail.getSkuId()) {
                    OrderRebateRecord record = new OrderRebateRecord();
                    record.setOrderNo(orderNo);
                    record.setSkuId(detail.getOrderDetailSkuId());
                    record.setStatus(OrderRebateStatusEnum.HAH_CORRECTION.getStatusCode());
                    LOGGER.info("修改收益状态(未售后的商品)-----updateRebateRecord-----收益信息-----{}", JsonUtil.toJSONString(record));
                    orderRebateRecordMapper.updateByPrimaryKeySelective(record);
                    continue;
                }
            //已售后
            }else{
                //3-已发货换货 || 6、已收货换货
                if (detail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.WAIT_RECEIVING_EXCHANGE.getTypeCode().intValue()
                        || detail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.FINISHED_EXCHANGE.getTypeCode().intValue()) {
                    OrderRebateRecord record = new OrderRebateRecord();
                    record.setOrderNo(orderNo);
                    record.setSkuId(detail.getOrderDetailSkuId());
                    record.setStatus(OrderRebateStatusEnum.HAH_CORRECTION.getStatusCode());
                    LOGGER.info("修改收益状态(已售后的商品 3-已发货换货 || 6、已收货换货)-----updateRebateRecord-----收益信息-----{}", JsonUtil.toJSONString(record));
                    orderRebateRecordMapper.updateByPrimaryKeySelective(record);
                    continue;
                }

                //2-已发货退货退款 || 5-已完成退货退款
                if ((detail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.WAIT_RECEIVING_REFUND_AND_RETURN.getTypeCode().intValue()
                        || detail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.FINISHED_REFUND_AND_RETURN.getTypeCode().intValue())) {
                    //输入物流正常 && 审核通过
                    if(detail.getAfterSaleStatus().intValue() == CommonStatusEnum.YES.getTypeCode().intValue()
                        && detail.getResultStatus().intValue() == AfterSaleAuditStatusEnum.YES.getTypeCode().intValue()){
                        OrderRebateRecord record = new OrderRebateRecord();
                        record.setOrderNo(orderNo);
                        record.setSkuId(detail.getOrderDetailSkuId());
                        record.setStatus(OrderRebateStatusEnum.HAS_CLOSED.getStatusCode());
                        LOGGER.info("修改收益状态(已售后的商品-审核同意 2-已发货退货退款 || 5-已完成退货退款)-----updateRebateRecord-----收益信息-----{}", JsonUtil.toJSONString(record));
                        orderRebateRecordMapper.updateByPrimaryKeySelective(record);
                        continue;
                    }else{
                        OrderRebateRecord record = new OrderRebateRecord();
                        record.setOrderNo(orderNo);
                        record.setSkuId(detail.getOrderDetailSkuId());
                        record.setStatus(OrderRebateStatusEnum.HAH_CORRECTION.getStatusCode());
                        LOGGER.info("修改收益状态(已售后的商品 -审核拒绝或者售后关闭（自动和手动） 2-已发货退货退款 || 5-已完成退货退款)-----updateRebateRecord-----收益信息-----{}", JsonUtil.toJSONString(record));
                        orderRebateRecordMapper.updateByPrimaryKeySelective(record);
                        continue;
                    }
                }
            }
        }
    }


    /**
     * @Description 修改订单信息
     * @author lining
     * @date 2019/1/17 10:33:50
     * @param orderNo status
     * @return
     */
    private void modifyOrderStatus(String orderNo,int status){
        OrderInfo orderInfo = new OrderInfo();
        Date now = new Date();
        orderInfo.setOrderNo(orderNo);
        orderInfo.setUpdated(now);
        orderInfo.setUpdatedBy(UpdatedByEnum.AFTERSALE.getTypeCode());
        if (status == TEMP_ORDER_STATUS_FINISHED) {
            orderInfo.setCompleteTime(now);
            orderInfo.setStatus(OrderStatusEnum.FINISHED.getStatusCode());
        } else if (status == TEMP_ORDER_STATUS_CLOSE) {
            orderInfo.setCloseTime(now);
            orderInfo.setStatus(OrderStatusEnum.CLOSE.getStatusCode());
        }
        LOGGER.info("修改订单状态-----updateOrderStatus-----订单信息-----{}", JsonUtil.toJSONString(orderInfo));
        infoMapper.updateByOrderNo(orderInfo);
    }

    /**
     * @Description 售后申请信息赋值
     * @author lining
     * @date 2019/1/11 19:14:15
     * @param condition  afterSaleDetail
     * @return
     */
	private void setAfterSaleDetailProperty(OrderAfterSaleApplyCondition condition, OrderAfterSaleDetail afterSaleDetail){
		BeanUtils.copyProperties(condition,afterSaleDetail);
		afterSaleDetail.setResultStatus(AfterSaleAuditStatusEnum.PROCESSING.getTypeCode());
		afterSaleDetail.setAfterSaleStatus(AfterSaleStatusEnum.NORMAL.getTypeCode());
		afterSaleDetail.setCompleteStatus(CommonStatusEnum.NO.getTypeCode());
		afterSaleDetail.setViewStatus(AfterSaleViewStatusEnum.WAIT_CHECKED.getTypeCode());
        afterSaleDetail.setApplyUser(String.valueOf(condition.getCustomerId()));
		Date now = new Date();
        afterSaleDetail.setApplyTime(now);
		afterSaleDetail.setCreatedBy(String.valueOf(condition.getCustomerId()));
		afterSaleDetail.setCreated(now);
		afterSaleDetail.setUpdatedBy(String.valueOf(condition.getCustomerId()));
		afterSaleDetail.setUpdated(now);
	}

	/**
	 * @Description 售后申请验证
	 * @author lining
	 * @date 2019/1/11 19:13:54
	 * @param afterSaleDetail
	 * @return
	 */
	private  void validateApply(OrderAfterSaleDetail afterSaleDetail){
		if(afterSaleDetail.getAfterSaleType().intValue() != OrderAfterSaleTypeEnum.WAIT_DELIVERING_REFUND.getTypeCode().intValue()
                && this.validateOrderAutoReceiveTime(afterSaleDetail.getOrderNo())){
			LOGGER.error("订单{}已自动确认收货，不能再进行任何操作！！",afterSaleDetail.getOrderNo());
			throw new BusinessException(BusinessCode.CODE_440601);
		}

		if(this.validateAfterSaleComplate(afterSaleDetail)){
            LOGGER.error("此订单{}发起过【未发货退款】售后,且售后未完成,不能重复发起售后！！",afterSaleDetail.getOrderNo());
            throw new BusinessException(BusinessCode.CODE_440615);
        }

		if(this.validateAfterSaleRefund(afterSaleDetail)){
            LOGGER.error("此订单{}发起过【未发货退款】售后,且已审核通过,不能重复发起售后！！",afterSaleDetail.getOrderNo());
            throw new BusinessException(BusinessCode.CODE_440607);
        }

		if(this.validateCanApply(afterSaleDetail)){
			if(null == afterSaleDetail.getSkuId()){
				LOGGER.error("订单{}已发起过售后，不能再次发起！！",afterSaleDetail.getOrderNo());
			}else{
				LOGGER.error("订单{}-商品{}已发起过售后，不能再次发起！！",afterSaleDetail.getOrderNo(),afterSaleDetail.getSkuId());
			}
			throw new BusinessException(BusinessCode.CODE_440602);
		}

	}

	private void validateOrderStatus(OrderAfterSaleDetail afterSaleDetail){
        OrderInfo orderInfo = infoMapper.selectByOrderNo(afterSaleDetail.getOrderNo());
	    if(afterSaleDetail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.WAIT_DELIVERING_REFUND.getTypeCode().intValue()
                && orderInfo.getStatus().intValue() !=  OrderStatusEnum.WAIT_DELIVERING.getStatusCode()){
            LOGGER.error("只能【待发货】状态下的订单才能发起【待发货退款】售后");
            throw new BusinessException(BusinessCode.CODE_440616);
        }

        if((afterSaleDetail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.WAIT_RECEIVING_EXCHANGE.getTypeCode().intValue()
                || afterSaleDetail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.WAIT_RECEIVING_REFUND_AND_RETURN.getTypeCode().intValue())
                && orderInfo.getStatus().intValue() !=  OrderStatusEnum.WAIT_RECEIVING.getStatusCode()){
            LOGGER.error("只能【待收货】状态下的订单才能发起【待收货-退款退货、待收货-换货】售后");
            throw new BusinessException(BusinessCode.CODE_440618);
        }

        if((afterSaleDetail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.FINISHED_REFUND_AND_RETURN.getTypeCode().intValue()
                || afterSaleDetail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.FINISHED_EXCHANGE.getTypeCode().intValue())
                && orderInfo.getStatus().intValue() !=  OrderStatusEnum.RECEIVIED.getStatusCode()){
            LOGGER.error("只能【已收货】状态下的订单才能发起【已收货-退款退货、已收货-换货】售后");
            throw new BusinessException(BusinessCode.CODE_440617);
        }
    }

	/**
	 * @Description 验证订单是否完成
	 * @author lining
	 * @date 2019/1/12 11:46:50
	 * @param orderNo
	 * @return 1-订单未完成 2-订单已完成 3-订单已关闭
	 */
	@Override
	public int getOrderStatus(String orderNo){
        //待发货退款完成 订单直接关闭
        if(this.getOrderStatusByAfterSale(orderNo)){
            LOGGER.info("验证订单是否完成-----getOrderStatus-----{} 待发货退款完成 订单直接关闭",orderNo);
            return TEMP_ORDER_STATUS_CLOSE;
        }
        //是否有未完成的售后
        boolean afterSaleStatusFlag = this.validateAfterSaleStatus(orderNo);
        //是否有未售后的商品
        boolean afterSaleFlag = this.validateAfterSale(orderNo);
        //订单是否到收货时间
        boolean autoCloseTimeFlag = this.validateOrderAutoReceiveTime(orderNo);
        //未到关闭时间
        if(!autoCloseTimeFlag){
            LOGGER.info("验证订单是否完成-----getOrderStatus-----{} 未到关闭时间",orderNo);
            return TEMP_ORDER_STATUS_NORMAL;
        }
        LOGGER.info("验证订单是否完成-----getOrderStatus-----{} 已到关闭时间",orderNo);

        //有未完成的售后
        if(afterSaleStatusFlag){
            LOGGER.info("验证订单是否完成-----getOrderStatus-----{} 有未完成的售后",orderNo);
           return TEMP_ORDER_STATUS_NORMAL;
        }

        LOGGER.info("验证订单是否完成-----getOrderStatus-----{} 没有未完成的售后",orderNo);
        //有未售后的商品
        if(afterSaleFlag){
            LOGGER.info("验证订单是否完成-----getOrderStatus-----{} 有未售后的商品",orderNo);
            return TEMP_ORDER_STATUS_FINISHED;
        }else{
            LOGGER.info("验证订单是否完成-----getOrderStatus-----{} 没有未售后的商品",orderNo);
            //有换货的售后 || 有拒绝的退货退款 || 有关闭或者取消的售后
            if(this.validateExchangeFlag(orderNo) || this.validateReturningFlag(orderNo) || this.validateAfterSaleCloseOrCancel(orderNo)){
                LOGGER.info("验证订单是否完成-----getOrderStatus-----{} 有 换货 或者 拒绝退货 或者 关闭 或者 撤销【非 待发货-仅退款】 的售后",orderNo);
                return TEMP_ORDER_STATUS_FINISHED;
            }else{
                LOGGER.info("验证订单是否完成-----getOrderStatus-----{} 没有 换货 或者 拒绝退货 或者 关闭 或者 撤销【非 待发货-仅退款】 的售后",orderNo);
                return TEMP_ORDER_STATUS_CLOSE;
            }



        }
	}

	/**
	 * @Description 验证订单是否有关闭的售后
	 * @author lining
	 * @date 2019/1/25 14:17:04
	 * @param orderNo
	 * @return
	 */
	private boolean validateAfterSaleCloseOrCancel(String orderNo){
        List<OrderAfterSaleDetail> lst = afterSaleDetailMapper.selectListByOrderNo(orderNo);
        for (OrderAfterSaleDetail detail: lst){
            if(detail.getResultStatus().intValue() == AfterSaleAuditStatusEnum.HANDLE_CLOSED.getTypeCode().intValue()
                || detail.getAfterSaleStatus().intValue() == CommonStatusEnum.NO.getTypeCode().intValue()){
                LOGGER.info("有关闭的售后");
                return true;
            }

            if(detail.getResultStatus().intValue() == AfterSaleAuditStatusEnum.CANCEL.getTypeCode().intValue()
                && detail.getAfterSaleType().intValue() != OrderAfterSaleTypeEnum.WAIT_DELIVERING_REFUND.getTypeCode().intValue()){
                LOGGER.info("有取消的售后-非【待发货-仅退款】");
                return true;
            }
        }
        return false;
    }

	/**
	 * @Description 判断订单下的售后是否有换货
	 * @author lining
	 * @date 2019/1/12 18:33:10
	 * @param orderNo
	 * @return true-有 false-没有
	 */
	private boolean validateExchangeFlag(String orderNo){
	    OrderAfterSaleDetail detail = new OrderAfterSaleDetail();
	    detail.setOrderNo(orderNo);
        detail.setResultStatus(AfterSaleAuditStatusEnum.YES.getTypeCode());
        detail.setAfterSaleType(OrderAfterSaleTypeEnum.FINISHED_EXCHANGE.getTypeCode());
        if(afterSaleDetailMapper.getApplyCount(detail)>0){
            LOGGER.info("售后有【已收货-换货】");
            return true;
        }
        detail.setAfterSaleType(OrderAfterSaleTypeEnum.WAIT_RECEIVING_EXCHANGE.getTypeCode());
        if(afterSaleDetailMapper.getApplyCount(detail)>0){
            LOGGER.info("售后有【待收货-换货】");
            return true;
        }
        return false;
    }

	/**
	 * @Description 判断是否有未完成的售后
	 * @author lining
	 * @date 2019/1/12 13:15:57
	 * @param orderNo
	 * @return true-有、false-没有
	 */
	private boolean validateAfterSaleStatus(String orderNo){
        OrderAfterSaleCondition condition = new OrderAfterSaleCondition();
        condition.setOrderNo(orderNo);
        List<OrderAfterSaleDetailVO> detailList = afterSaleDetailMapper.selectOrderAfterSaleDetailByConditionForValidate(condition);
        for (OrderAfterSaleDetailVO detail : detailList) {
            //有未完成的售后
            if(detail.getCompleteStatus().intValue() == CommonStatusEnum.NO.getTypeCode().intValue()){
                return true;
            }
        }
        return false;
    }

	/**
	 * @Description 判断是否有未售后的商品
	 * @author lining
	 * @date 2019/1/12 13:10:40
	 * @param orderNo
	 * @return true-有、false-没有
	 */
	private boolean validateAfterSale(String orderNo){
        List<Long> skuIdList = afterSaleDetailMapper.selectSkuIdByOrderNo(orderNo);
        for (Long skuId : skuIdList){
            //有未售后的sku
            if(null == skuId){
                return true;
            }
        }
        return false;
    }

    /**
     * @Description 验证订单待发货退款是否完成
     * @author lining
     * @date 2019/1/12 14:20:02
     * @param orderNo
     * @return true-是，false-否
     */
    private boolean getOrderStatusByAfterSale(String orderNo){
        OrderAfterSaleDetail afterSaleDetail = afterSaleDetailMapper.selectOrderAfterSaleDetailByOrderNo(orderNo);
        if(null != afterSaleDetail && afterSaleDetail.getResultStatus().intValue()==CommonStatusEnum.YES.getTypeCode().intValue() && afterSaleDetail.getCompleteStatus().intValue() == CommonStatusEnum.YES.getTypeCode().intValue()){
            return true;
        }
        return false;
    }

    /**
     * @Description 生成售后单号
     * @author lining
     * @date 2019/1/17 14:25:20
     * @param afterSaleDetail
     * @return
     */
    private String generateAfterSaleNo(OrderAfterSaleDetail afterSaleDetail) {
        String afterSaleNo = null;
        Date date = new Date();
        String orderNoDateTimeFormatter = "yyMMddHH";
        String randomFormat = "%05d";
        UUID uuid = UUID.randomUUID();
        int hashCodeV = (uuid.toString() + System.currentTimeMillis()).hashCode();
        if (hashCodeV < 0) {
            // 有可能是负数
            hashCodeV = -hashCodeV;
        }
        while (hashCodeV > MAX_ORDER_POSTFIX) {
            hashCodeV = hashCodeV >> 1;
        }
        String key="afterSale:no";
        if(StringUtils.isBlank(cache.get(key))){
            cache.setex(key,24*60*60,"0");
        }
        Long suff = cache.incrBy(key,1L);
        afterSaleNo = "SH" +afterSaleDetail.getAfterSaleType().intValue()+ DateFormatUtils.format(date, orderNoDateTimeFormatter) +String.format(randomFormat,hashCodeV)+ String.format(randomFormat, suff);
        return afterSaleNo;
    }

    /**
     * @Description 小程序售后列表
     * @author lining
     * @date 2019/1/17 20:40:37
     * @param condition
     * @return
     */
    @Override
    public PagedList<OrderInfoAfterSaleVO>selectAfterSaleInfo(OrderQueryCondition condition){
        PagedList<OrderInfoAfterSaleVO> result = new PagedList<>();
        condition.setStartNum((condition.getPageNo()-1)*condition.getPageSize());
        List<OrderInfoAfterSaleVO> afterSaleVOList = afterSaleDetailMapper.selectAfterSaleInfo(condition);
        result.setPageNo(condition.getPageNo());
        result.setPageSize(condition.getPageSize());
        result.setData(afterSaleVOList);
        result.setTotalRows(afterSaleDetailMapper.countAfterSaleInfo(condition));
        return result;
    }

    /**
     * @Description 小程序售后详情
     * @author lining
     * @date 2019/1/17 20:40:37
     * @param condition
     * @return
     */
    @Override
    public OrderInfoAfterSaleVO getAfterSaleInfo(OrderQueryCondition condition){
        List<OrderInfoAfterSaleVO> afterSaleVOList = afterSaleDetailMapper.selectAfterSaleInfo(condition);
        if(!CollectionUtils.isEmpty(afterSaleVOList)){
            return afterSaleVOList.get(0);
        }
        return null;
    }

    /**
     * @Description 手动关闭售后
     * @author lining
     * @date 2019/1/21 17:44:23
     * @param afterSaleDetailId  customerId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeAfterSale(Long afterSaleDetailId,Long customerId){
        this.validateCloseAfterSaleStatus(afterSaleDetailId);
        this.validateReturning(afterSaleDetailId);
        OrderAfterSaleDetail afterSaleDetail = afterSaleDetailMapper.selectByPrimaryKey(afterSaleDetailId);
        String lockKey = CacheName.CACHE_KEY_MODIFY_AFTER_SALE+afterSaleDetail.getOrderNo();
        if(null != afterSaleDetail.getSkuId()) {
            lockKey+=afterSaleDetail.getSkuId();
        }
        Lock lock = new RedisLock(cache, lockKey, AFTER_SALE_UPDATE_LOCK_EXPIRES_TIME);
        int result = 0;
        if (lock.tryLock()) {
            try {
                //关闭售后
                this.updateAfterSaleStatus(afterSaleDetail,customerId);
                try{
                    //日志
                    this.saveOrderLog4CloseAfterSale(afterSaleDetail);
                }catch (Exception e){
                    LOGGER.info("手动关闭售后-日志异常,不回滚",e);
                }
                //售后完成修改订单、收益...
                this.updateOrderStatus(afterSaleDetail.getOrderNo());
            } finally {
                lock.unlock();
            }
        }else {
            throw new BusinessException(BusinessCode.CODE_440603);
        }
    }

    /**
     * @Description 关闭售后时验证是否在退款中
     * @author lining
     * @date 2019/1/24 10:25:15
     * @param afterSaleDetailId
     * @return
     */
    private void validateReturning(Long afterSaleDetailId){
        OrderAfterSaleDetail afterSaleDetail = afterSaleDetailMapper.selectByPrimaryKey(afterSaleDetailId);
        OrderInfoVO orderInfoVO = orderService.selectInfoByOrderNo(afterSaleDetail.getOrderNo());
        if(orderInfoVO.getStatus() == OrderStatusEnum.CLOSE.getStatusCode()
            || orderInfoVO.getStatus() == OrderStatusEnum.FINISHED.getStatusCode()){
            LOGGER.info("订单已闭环,不能关闭售后");
            throw new BusinessException(BusinessCode.CODE_440620);
        }

        if(afterSaleDetail.getCompleteStatus().intValue() == CommonStatusEnum.YES.getTypeCode().intValue()){
            LOGGER.info("此售后已完成,不能关闭售后");
            throw new BusinessException(BusinessCode.CODE_440621);
        }

        /*if(afterSaleDetail.getViewStatus().intValue() == AfterSaleViewStatusEnum.EXCHANGING.getTypeCode().intValue()
                || afterSaleDetail.getViewStatus().intValue() == AfterSaleViewStatusEnum.RETURNING.getTypeCode().intValue()){
            LOGGER.info("此售后已经在 退货/换货 中,不能关闭");
            throw new BusinessException(BusinessCode.CODE_440623);
        }*/

        if(afterSaleDetail.getViewStatus().intValue() == AfterSaleViewStatusEnum.REFUNDING.getTypeCode().intValue()
            || afterSaleDetail.getViewStatus().intValue() == AfterSaleViewStatusEnum.REFUNDED.getTypeCode().intValue()){
            LOGGER.info("此售后已经在退款,不能关闭");
            throw new BusinessException(BusinessCode.CODE_440619);
        }

        //待发货-仅退款 已审核同意，不能关闭售后
        if(afterSaleDetail.getAfterSaleType().intValue() == OrderAfterSaleTypeEnum.WAIT_DELIVERING_REFUND.getTypeCode().intValue()
                && afterSaleDetail.getResultStatus().intValue() == AfterSaleAuditStatusEnum.YES.getTypeCode().intValue()){
            LOGGER.info("售后【待发货-仅退款】 已审核同意，不能关闭售后！！订单号：{} ",afterSaleDetail.getOrderNo());
            throw new BusinessException(BusinessCode.CODE_440622);
        }
    }

    private void updateAfterSaleStatus(OrderAfterSaleDetail afterSaleDetail,Long customerId){
        OrderAfterSaleDetail detail = new OrderAfterSaleDetail();
        Date now = new Date();
        detail.setId(afterSaleDetail.getId());
        detail.setCompleteStatus(CommonStatusEnum.YES.getTypeCode());
        detail.setCompleteTime(now);
        detail.setUpdated(now);
        detail.setUpdatedBy(String.valueOf(customerId));
        detail.setResultStatus(AfterSaleAuditStatusEnum.HANDLE_CLOSED.getTypeCode());
        detail.setViewStatus(AfterSaleViewStatusEnum.HANDLE_CLOSED.getTypeCode());
        LOGGER.info("强制关闭售后-----closeAfterSale-----售后信息：{}",detail);
        //手动强制关闭售后
        afterSaleDetailMapper.updateByPrimaryKeySelective(detail);
    }


    /**
     * @Description 验证售后强制关闭
     * @author lining
     * @date 2019/1/21 18:54:39
     * @param afterSaleDetailId
     * @return
     */
    @Override
    public void validateCloseAfterSaleStatus(Long afterSaleDetailId){
        OrderAfterSaleDetail afterSaleDetail = afterSaleDetailMapper.selectByPrimaryKey(afterSaleDetailId);

        if(afterSaleDetail.getResultStatus().intValue() == AfterSaleAuditStatusEnum.HANDLE_CLOSED.getTypeCode().intValue()){
            LOGGER.info("此售后已关闭！！订单号：{} 售后单号:{}",afterSaleDetail.getOrderNo(),afterSaleDetail.getAfterSaleNo());
            throw new BusinessException(BusinessCode.CODE_440613);
        }
    }

    /**
     * @Description 判断订单下的售后是否有拒绝的退款
     * @author lining
     * @date 2019/1/12 18:33:10
     * @param orderNo
     * @return true-有 false-没有
     */
    private boolean validateReturningFlag(String orderNo){
        OrderAfterSaleDetail detail = new OrderAfterSaleDetail();
        detail.setOrderNo(orderNo);
        detail.setResultStatus(AfterSaleAuditStatusEnum.NO.getTypeCode());
        detail.setAfterSaleType(OrderAfterSaleTypeEnum.FINISHED_REFUND_AND_RETURN.getTypeCode());
        if(afterSaleDetailMapper.getApplyCount(detail)>0){
            LOGGER.info("有拒绝的【已收货-退款退货】");
            return true;
        }
        detail.setAfterSaleType(OrderAfterSaleTypeEnum.WAIT_RECEIVING_REFUND_AND_RETURN.getTypeCode());
        if(afterSaleDetailMapper.getApplyCount(detail)>0){
            LOGGER.info("有拒绝的【待收货-退款退货】");
            return true;
        }
        return false;
    }

	/**
	 * 保存手动关闭售后日志
	 * @param afterSaleDetail
	 */
	private void saveOrderLog4CloseAfterSale(OrderAfterSaleDetail afterSaleDetail){
		OrderLog orderLog = new OrderLog();
		orderLog.setOrderNo(afterSaleDetail.getOrderNo());
		orderLog.setSkuId(afterSaleDetail.getSkuId());
		String operationPropertity = OrderOperationPropertyEnum.HAND_CLOSE_AFTER_SALE.getPropertyDes();
		orderLog.setCreated(new Date());
		orderLog.setOperationProperty(operationPropertity);
		LOGGER.info("售后-手动关闭售后日志-----saveOrderLog-----{}", JsonUtil.toJSONString(orderLog));
		orderLogMapper.insertSelective(orderLog);
	}
}